package cn.genmer.test.security.aop;

import cn.genmer.test.security.annotation.Timed;
import cn.genmer.test.security.annotation.TimedContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

@Aspect
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Component
public class TimingAspect {

    private static final Logger logger = LoggerFactory.getLogger(TimingAspect.class);

    @Pointcut("@annotation(Timed)")
    public void record() {
    }

    private final String MAIN = "main";


    @Around("record()")
    public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        String methodName = pjp.getSignature().toShortString();
        String timedValue = getTimedValue(pjp);
        if (timedValue.equals(MAIN)) {
            return pjp.proceed();
        }

        TimedContext.start(methodName);

        Object result;
        try {
            result = pjp.proceed();
        } finally {
            long duration = TimedContext.stop(methodName);
        }

        return result;
    }

    @Around("execution(* cn.genmer.test.security.*.*(..)) && @annotation(Timed)")
    public Object measureMainMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        String methodName = pjp.getSignature().toShortString();
        String timedValue = getTimedValue(pjp);

        if (!timedValue.equals(MAIN)) {
            return pjp.proceed();
        }
        TimedContext.start(methodName);

        Object result;
        try {
            result = pjp.proceed();
        } finally {
            long duration = TimedContext.stop(methodName);
            Object[] args = pjp.getArgs();
//            RequestParams requestParams = null;
//            String isSimpleMatch = null;
//
//            // 遍历方法的所有参数
//            for (Object arg : args) {
//
//                if (arg instanceof RequestParams) {
//                    // 如果参数类型是 Boolean 并且变量名是 isSimpleMatch
//                    requestParams = (RequestParams) arg;
//                    isSimpleMatch = requestParams.getIsSimpleMatch();
//                    break;
//                }
//            }

            if (duration > 400 && "1".equals("isSimpleMatch")) {
                Map<String, Long> timeRecords = TimedContext.getTimeRecords();
                logger.error("Execution time summary for {}: {}, requestParams: {}", methodName, timeRecords, null);
            }

            // 清除上下文中的数据
            TimedContext.clear();
        }

        return result;
    }

    private String getTimedValue(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        String timedValue = "";
        // 获取方法上的 @Timed 注解
        Timed timedAnnotation = method.getAnnotation(Timed.class);

        // 如果方法上有 @Timed 注解，获取注解的值
        if (timedAnnotation != null) {
            timedValue = timedAnnotation.value();
        }

        return timedValue;
    }
}
